﻿


using System;
using System.Globalization;

namespace Fozzy.Gedcom
{
    /// <summary>
    /// Parses one line in a GEDCOM file.
    /// </summary>
    public class Line                           : Name
    {

        #region fields

            const char                          Char_n      = '\n'                                                                  ;
            static string                       n           = Char_n.ToString()                                                     ;
            const string                        r           = "\r"                                                                  ;
            const string                        rn          = "\r\n"                                                                ;
            const string                        data        = "data"                                                                ;
        // Parts of the GEDCOM line.
        //private int level;
        //private string tag;
        //private string data;

            // Expression pattern used to parse the GEDCOM line.
            //private readonly RegEx regSplit = new RegEx( @"(?<level>\d+)\s+(?<tag>[\S]+)(\s+(?<data>.+))?");

            // Expression pattern used to clean up the GEDCOM line. Only allow viewable characters.
            //private readonly RegEx regClean = new RegEx(@"[^\x20-\x7e]")    ;
            //const int                           Limit                   = 200                                           ;

        #endregion

        #region States
            private bool                        Be_Pointer              { get { return Tag.Be_Pointer                           ; } }
            private new bool                    Be_Clean                { get { return Be_Without_N  && Be_Without_R            ; } }
            private bool                        Be_Without_N            { get { return !Contains(n)                             ; } }
            private bool                        Be_Without_R            { get { return !Contains(r)                             ; } }
        #endregion

        #region Structure
            private Tag                         Tag                     { get { return new Tag(this)                            ; } }
        #endregion

        #region Items
            private Name                        Cleaner                 { get { return new Name(ToString().Replace(rn, n).Replace(r, n))    ; } }
            private Name                        Splitter                { get { return new Name(new Fozzy.Name(ToString().Split(Char_n)))   ; } }
        #endregion

        #region Constructeur
            public Line()                                               
            { }
            public Line(string content)                                 : base(content)
            { }
            public Line(Level level, string content)                    : base(level, content)
            { }

        #endregion

            //public override void Export()
            //{
            //    Fozzy.Being.Static.Map.Write(this)               ;
            //}

            //public override void Export()
            //{
            //    base.Export();
            //    //    if (!string.IsNullOrEmpty(person.NickName))     WriteLine(2, "NICK", person.NickName)       ;
            //    if (!Name.Be_Error) new Line(Alias, Name.ToString())  ;
            //}

            protected override void Prepare()
            {
                base.Prepare()                                          ;
                De_Point()                                              ;
            }

            //                writer.WriteLine(string.Format(CultureInfo.InvariantCulture,  "{0} {1} {2}", level, tag, chunk));
            //            }
            //            else
            //            {
            //                writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", level + 1, "CONC", chunk));
            //            }
            //        }


        /// <summary>
        /// Parse the Level, Tag, and Data fields from the GEDCOM line.
        /// The following is a sample GEDCOM line:
        /// 
        ///    2 NAME Personal Ancestral File
        ///    
        /// The Level = 2, Tag = NAME, and Data = Personal Ancestral File.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void De_Point()
        {
            try
            {
                // Init values.
                Re_Set();

                // Return right away is nothing to parse.
                //if (string.IsNullOrEmpty(text)) return false;
                if (!Be_Error)
                {
                    // Clean up the line by only allowing viewable characters.
                    //text = regClean.Replace(text, "");
                    Clean()                                                                         ;
                    if(Be_Pointer) Reach()                                                          ;
                }
                //return true;
            }
            catch
            {
                // This line is invalid, clear all values.
                Re_Set()                                                                            ;
                //return false                                                                      ;
            }
        }

        private void Reach()
        {
            Tag.Reach(this)                                                                         ;
        }

        private void Clean()
        {
            Name.Clean(new Clean())                                                                 ;
            Set(Cleaner)                                                                            ;
            Set(Splitter)                                                                           ;
        }

        /// <summary>
        /// Reset all values.
        /// </summary>
        public override void Re_Set()
        {
            base    .Re_Set()                                                                       ;
            Tag     .Re_Set()                                                                       ;
            //Level   .Re_Set()                                                                       ;
        }

        private void Set(_Match match)
        {
            Set(new Tag     (match))                                                                ;
        }
    }
}
